#include<iostream>
#include<signal.h>
#include <openssl/sha.h>
#include"../comm/httplib.h"
#include"oj_control.hpp"
#include"oj_model_mysql.hpp"

using namespace httplib;
using namespace ns_control;

static Control *ctrl_ptr=nullptr;


// 信号处理函数：收到SIGQUIT信号（比如用户按Ctrl+\），重启所有编译主机
void Recovery(int sigo)
{
    ctrl_ptr->RecoveryMachine();
}

int main()
{
    // 注册信号处理（收到SIGQUIT信号，调用Recovery重启主机）
    signal(SIGQUIT,Recovery);

    //用户请求的服务路由功能
    Server svr;
    Control ctrl;
    ctrl_ptr=&ctrl;


    // 注册接口
    svr.Post("/api/register", [&](const Request& req, Response& res) {
        // 提取请求参数：username和password（用户表单里的字段名）
        std::string username = req.get_param_value("username");
        std::string password = req.get_param_value("password");
        
        bool success = ctrl.DoRegister(username, password);
        LOG(INFO) << "注册接口返回: " << (success ? "success" : "failed"); // 新增日志
        res.set_content(success ? "success" : "fail", "text/plain");
    });

    // 登录接口
    svr.Post("/api/login", [&](const Request& req, Response& res) {
        std::string username = req.get_param_value("username");
        std::string password = req.get_param_value("password");
        
        std::string session_id;
        // 调用修改后的DoLogin，获取SessionID
        bool success = ctrl.DoLogin(username, password, &session_id);
    
        if (success) 
        {
            // Cookie仅存SessionID，Path=/表示全站生效，Max-Age=7天
            res.set_header("Set-Cookie", "oj_session_id=" + session_id + "; Path=/; Max-Age=604800; HttpOnly");
            res.set_content("success", "text/plain");
        } 
        else 
        {
            res.set_content("fail", "text/plain");
        }
        
    });

    // 验证登录状态接口（供前端检查）

    svr.Get("/api/check_login", [&](const Request& req, Response& res) {
        auto it = req.headers.find("Cookie");
        if (it == req.headers.end()) 
        {
            res.set_content("not_login", "text/plain");
            return;
        }

        std::string cookie_str = it->second;
        size_t pos = cookie_str.find("oj_session_id=");
        if (pos == std::string::npos) 
        {
            res.set_content("not_login", "text/plain");
            return;
        }

        // 提取SessionID（"oj_session_id="长度为14）
        std::string session_id = cookie_str.substr(pos + 14);
        std::string username;

        // 2. 通过SessionID查询Session
        if (ctrl.GetSession(session_id, &username)) 
        {
            res.set_content(username, "text/plain");  // 登录有效，返回用户名
        }   
        else 
        {
            res.set_content("not_login", "text/plain");  // Session无效/过期
        }
    });

    // 退出登录接口
    svr.Get("/api/logout", [&](const Request& req, Response& res) {
        // 1. 提取SessionID并销毁Session
        auto it = req.headers.find("Cookie");
        if (it != req.headers.end()) 
        {
            std::string cookie_str = it->second;
            size_t pos = cookie_str.find("oj_session_id=");
            if (pos != std::string::npos) 
            {
                std::string session_id = cookie_str.substr(pos + 14);
                ctrl.DestroySession(session_id);  // 销毁服务器端Session
            }
        }

        // 2. 让Cookie立即过期（浏览器删除Cookie）
        res.set_header("Set-Cookie", "oj_session_id=; Path=/; Max-Age=0; HttpOnly");
        res.set_content("success", "text/plain");
    });


    //获取所有的题目列表

    svr.Get("/all_questions",[&ctrl](const Request& req,Response& resp){
        std::string html;
        ctrl.AllQuestions(&html);
        resp.set_content(html,"text/html;charset=utf-8");
    });

    //用户要根据题目编号，获取题目的内容
    // 正则表达式\d代表数字 +代表一个或者多个
    svr.Get(R"(/question/(\d+))",[&ctrl](const Request& req,Response& resp){
        std::string number=req.matches[1];
        std::string html;
        ctrl.Question(number,&html);
        resp.set_content(html,"text/html;charset=utf-8");
    });
    

    //用户提交代码，使用判题功能(1.每道题的测试用例 2.compile_and_run)
    svr.Post(R"(/judge/(\d+))",[&ctrl](const Request& req,Response& resp){
        std::string number=req.matches[1];
        std::string result_json;
        ctrl.Judge(number,req.body,&result_json);
        resp.set_content(result_json,"application/json;charset=utf-8");
        //resp.set_content("判定指定题目: "+number,"text/plain;charset=utf-8");
    });

    svr.set_base_dir("./wwwroot");
    svr.listen("0.0.0.0",8080);
    return 0;
}